package com.abigdreamer.swing.app.skin;

import java.awt.CardLayout;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import javax.swing.ButtonGroup;
import javax.swing.Icon;
import javax.swing.JComponent;
import javax.swing.JMenu;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.border.EmptyBorder;
import javax.swing.event.MouseInputListener;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicMenuUI;

import com.abigdreamer.swing.app.SwingUtil;
import com.abigdreamer.swing.component.UIUtil;

import craky.component.JImagePane;
import craky.componentc.CRootPaneUI;
import craky.componentc.JCSlider;
import craky.componentc.JCToggleButton;
import craky.layout.LineLayout;
import craky.util.Config;

public class SkinMenu
  extends JMenu
{
  private static final long serialVersionUID = -2020810008867284350L;
  private static final Icon ICON = SwingUtil.getIcon("skin_button_icon.png");
  private static final Image ROLLOVER_IMAGE = SwingUtil.getImage("common_button_rollover_bg.png", true);
  private static final Image PRESSED_IMAGE = SwingUtil.getImage("skin_button_pressed_bg.png", true);
  private Config config;
  private SkinMgr skinMgr;
  private JImagePane mainPane;
  private JImagePane skinDispalyPane;
  private JImagePane skinListPane;
  private JImagePane modeDisplayPane;
  private DeleteConfirmPane confirmPane;
  private SkinUnit[] units;
  private JPopupMenu popup;
  private CardLayout mainCardLayout;
  private CardLayout skinDispalyCardLayout;
  private Rectangle skinListBounds;
  
  public SkinMenu()
  {
    setUI(new SkinMenuUI());
    
    this.config = new Config(SkinConst.CONFIG_PATH);
    this.skinMgr = new SkinMgr(this);
    this.units = new SkinUnit[14];
    setPreferredSize(new Dimension(20, 20));
    initUI();
  }
  
  private void initUI()
  {
    this.popup = getPopupMenu();
    this.mainPane = new JImagePane(SwingUtil.getImage("skin_popup_bg.png"), "Center");
    this.confirmPane = new DeleteConfirmPane(this.skinMgr);
    this.skinDispalyPane = new JImagePane(SwingUtil.getImage("skin_list_bg.png"), "Center");
    this.skinListPane = new JImagePane(SwingUtil.getImage("skin_unit_bg.png"), "Center");
    this.modeDisplayPane = new JImagePane();
    setToolTipText("更改外观");
    setOpaque(false);
    setFocusable(false);
    setBorder(new EmptyBorder(0, 0, 0, 0));
    setMargin(new Insets(0, 0, 0, 0));
    setDelay(200);
    setIconTextGap(0);
    setBorderPainted(false);
    setRolloverEnabled(true);
    this.confirmPane.setName("Dialog");
    this.mainPane.setName("Main");
    this.mainPane.setImageOnly(true);
    this.mainPane.setBorder(new EmptyBorder(0, 0, 0, 0));
    this.mainPane.setLayout(new LineLayout(0, 0, 0, 0, 0, 10, 10, 1));
    this.skinDispalyPane.setImageOnly(true);
    this.skinDispalyPane.setPreferredSize(new Dimension(236, 97));
    this.skinDispalyPane.setBorder(new EmptyBorder(2, 2, 2, 2));
    this.skinDispalyPane.setLayout(this.skinDispalyCardLayout = new CardLayout());
    this.skinListPane.setImageOnly(true);
    this.skinListPane.setName("SkinList");
    this.skinListPane.setBorder(new EmptyBorder(5, 8, 5, 8));
    this.skinListPane.setLayout(new GridLayout(2, 7, 1, 1));
    this.skinListPane.setFilledBorderArea(true);
    this.modeDisplayPane.setImageOnly(true);
    this.modeDisplayPane.setName("ModeDispaly");
    this.modeDisplayPane.setBorder(new EmptyBorder(0, 0, 0, 0));
    this.popup.setOpaque(false);
    this.popup.setBorder(new EmptyBorder(0, 0, 0, 0));
    this.popup.setBorderPainted(false);
    this.popup.setFocusable(false);
    this.popup.setLayout(this.mainCardLayout = new CardLayout());
    this.popup.setPreferredSize(new Dimension(236, 152));
    this.popup.addPopupMenuListener(this.skinMgr);
    this.skinDispalyPane.add(this.skinListPane, this.skinListPane.getName());
    this.skinDispalyPane.add(this.modeDisplayPane, this.modeDisplayPane.getName());
    this.mainPane.add(this.skinDispalyPane, "Start");
    this.mainPane.add(createModePane(), "Start");
    this.mainPane.add(createAlphaPane(), "MiddleFill");
    this.popup.add(this.mainPane, this.mainPane.getName());
    this.popup.add(this.confirmPane, this.confirmPane.getName());
    this.skinDispalyCardLayout.show(this.skinDispalyPane, this.skinListPane.getName());
    initSkinUnits();
    cacheSkinListBounds();
  }
  
  private void cacheSkinListBounds()
  {
    Dimension parentSize = this.skinDispalyPane.getPreferredSize();
    Insets parentInsets = this.skinDispalyPane.getInsets();
    Insets insets = this.skinListPane.getInsets();
    int width = parentSize.width - parentInsets.left - parentInsets.right - insets.left - insets.right;
    int height = parentSize.height - parentInsets.top - parentInsets.bottom - insets.top - insets.bottom;
    this.skinListBounds = new Rectangle(insets.left, insets.top, width, height);
  }
  
  private void initSkinUnits()
  {
    int length = this.units.length;
    for (int i = 0; i < length; i++)
    {
      this.units[i] = new SkinUnit(this.skinMgr);
      this.skinListPane.add(this.units[i]);
    }
    this.units[(length - 1)].setLast(true);
    resetSkins();
  }
  
  public void resetSkins()
  {
    Iterator<Skin> skins = SkinManager.getAllSkins().values().iterator();
    
    int index = 1;
    while (index < this.units.length)
    {
      Skin skin = skins.hasNext() ? (Skin)skins.next() : null;
      if ((skin == null) || (!skin.isDefault())) {
        this.units[(index++)].setSkin(skin);
      }
    }
    this.units[0].setSkin(SkinManager.getSkin("默认皮肤"));
  }
  
  private JPanel createModePane()
  {
    JPanel modePane = new JPanel(new GridLayout(1, 3));
    ButtonGroup group = new ButtonGroup();
    JCToggleButton btnFill = new JCToggleButton();
    JCToggleButton btnTiled = new JCToggleButton();
    JCToggleButton btnScaled = new JCToggleButton();
    Map<String, JCToggleButton> buttonMap = new HashMap();
    modePane.setBorder(new EmptyBorder(0, 4, 1, 4));
    modePane.setPreferredSize(new Dimension(236, 40));
    modePane.setOpaque(false);
    btnFill.setFocusable(false);
    btnFill.setToolTipText("填充");
    btnFill.setImage(SwingUtil.getImage("skin_fill_small.png", true));
    btnFill.setRolloverImage(SwingUtil.getImage("skin_fill_rollover.png", true));
    btnFill.setSelectedImage(SwingUtil.getImage("skin_fill_sel.png", true));
    btnFill.putClientProperty("BigImage", SwingUtil.getImage("skin_fill_big.png", true));
    btnFill.putClientProperty("EventKey", "SkinModePreview");
    btnFill.putClientProperty("SkinModeValue", CRootPaneUI.ImageDisplayMode.FILL);
    btnFill.addMouseListener(this.skinMgr);
    btnTiled.setFocusable(false);
    btnTiled.setToolTipText("平铺");
    btnTiled.setImage(SwingUtil.getImage("skin_tiled_small.png", true));
    btnTiled.setRolloverImage(SwingUtil.getImage("skin_tiled_rollover.png", true));
    btnTiled.setSelectedImage(SwingUtil.getImage("skin_tiled_sel.png", true));
    btnTiled.putClientProperty("BigImage", SwingUtil.getImage("skin_tiled_big.png", true));
    btnTiled.putClientProperty("EventKey", "SkinModePreview");
    btnTiled.putClientProperty("SkinModeValue", CRootPaneUI.ImageDisplayMode.TILED);
    btnTiled.addMouseListener(this.skinMgr);
    btnScaled.setFocusable(false);
    btnScaled.setToolTipText("拉伸");
    btnScaled.setImage(SwingUtil.getImage("skin_scaled_small.png", true));
    btnScaled.setRolloverImage(SwingUtil.getImage("skin_scaled_rollover.png", true));
    btnScaled.setSelectedImage(SwingUtil.getImage("skin_scaled_sel.png", true));
    btnScaled.putClientProperty("BigImage", SwingUtil.getImage("skin_scaled_big.png", true));
    btnScaled.putClientProperty("EventKey", "SkinModePreview");
    btnScaled.putClientProperty("SkinModeValue", CRootPaneUI.ImageDisplayMode.SCALED);
    btnScaled.addMouseListener(this.skinMgr);
    buttonMap.put(CRootPaneUI.ImageDisplayMode.FILL.toString(), btnFill);
    buttonMap.put(CRootPaneUI.ImageDisplayMode.TILED.toString(), btnTiled);
    buttonMap.put(CRootPaneUI.ImageDisplayMode.SCALED.toString(), btnScaled);
    ((JCToggleButton)buttonMap.get(this.config.getProperty("Skin_Mode", "FILL"))).setSelected(true);
    btnFill.addActionListener(this.skinMgr);
    btnTiled.addActionListener(this.skinMgr);
    btnScaled.addActionListener(this.skinMgr);
    group.add(btnFill);
    group.add(btnTiled);
    group.add(btnScaled);
    modePane.add(btnFill);
    modePane.add(btnTiled);
    modePane.add(btnScaled);
    return modePane;
  }
  
  private JPanel createAlphaPane()
  {
    int bgAlphaValue = (int)(Float.valueOf(this.config.getProperty("Skin_Alpha", "0.50")).floatValue() * 100.0F);
    int winAlphaValue = (int)(Float.valueOf(this.config.getProperty("Win_Alpha", "1.0")).floatValue() * 100.0F);
    JPanel alphaPane = new JPanel(new GridLayout(1, 2));
    JCSlider bgAlphaSlider = new JCSlider(0, 0, 100, bgAlphaValue);
    JCSlider winAlphaSlider = new JCSlider(0, 20, 100, winAlphaValue);
    alphaPane.setBorder(new EmptyBorder(0, 4, 2, 3));
    alphaPane.setOpaque(false);
    bgAlphaSlider.setToolTipText("皮肤透明度");
    bgAlphaSlider.setMiniMode(true);
    bgAlphaSlider.putClientProperty("EventKey", "SkinAlphaChanged");
    bgAlphaSlider.addChangeListener(this.skinMgr);
    bgAlphaSlider.addMouseListener(this.skinMgr);
    winAlphaSlider.setToolTipText("窗体透明度");
    winAlphaSlider.setMiniMode(true);
    winAlphaSlider.putClientProperty("EventKey", "WinAlphaChanged");
    winAlphaSlider.addChangeListener(this.skinMgr);
    winAlphaSlider.addMouseListener(this.skinMgr);
    alphaPane.add(bgAlphaSlider);
    if (UIUtil.isTranslucencySupported()) {
      alphaPane.add(winAlphaSlider);
    }
    return alphaPane;
  }
  
  protected void paintComponent(Graphics g)
  {
    int width = getWidth();
    int height = getHeight();
    int iconWidth = ICON.getIconWidth();
    int iconHeight = ICON.getIconHeight();
    if (getModel().isSelected()) {
      UIUtil.paintImage(g, PRESSED_IMAGE, new Insets(2, 2, 2, 2), new Rectangle(0, 0, width, height), this);
    } else if (getModel().isRollover()) {
      UIUtil.paintImage(g, ROLLOVER_IMAGE, new Insets(2, 2, 2, 2), new Rectangle(0, 0, width, height), this);
    }
    ICON.paintIcon(this, g, (width - iconWidth) / 2, (height - iconHeight) / 2);
  }
  
  public void modePreview(Image image, boolean hidden)
  {
    if (hidden)
    {
      this.skinDispalyCardLayout.show(this.skinDispalyPane, this.skinListPane.getName());
    }
    else
    {
      this.modeDisplayPane.setImage(image);
      this.skinDispalyCardLayout.show(this.skinDispalyPane, this.modeDisplayPane.getName());
    }
  }
  
  public Rectangle getSkinListBounds()
  {
    return this.skinListBounds;
  }
  
  public void showPane(boolean isMain, Skin skin)
  {
    if (!isMain)
    {
      SkinManager.changeSkin(SkinManager.getCurrentSkin(), false);
      this.confirmPane.updateBackground(skin, this.mainPane);
    }
    this.mainCardLayout.show(this.popup, isMain ? this.mainPane.getName() : this.confirmPane.getName());
  }
  
  @Deprecated
  public void updateUI() {}
  
  private static class SkinMenuUI
    extends BasicMenuUI
  {
    public static ComponentUI createUI(JComponent c)
    {
      return new SkinMenuUI();
    }
    
    protected MouseInputListener createMouseInputListener(JComponent c)
    {
      return new MouseInputHandler();
    }
    
    protected class MouseInputHandler
      extends BasicMenuUI.MouseInputHandler
    {
      protected MouseInputHandler()
      {
        super();
      }
      
      public void mouseEntered(MouseEvent evt)
      {
        ((JMenu)evt.getSource()).getModel().setRollover(true);
      }
      
      public void mouseExited(MouseEvent evt)
      {
        ((JMenu)evt.getSource()).getModel().setRollover(false);
      }
    }
  }
}
